static char* OPT_erase_only; /* erase_only ? command option */
static char* OPT_log_enable; /* enable ? command option */
static char* csv_file; /* csv ? command option */
+static char* OPT_block_size; /* block_size ? command option */
static enum MTK_DEVICE_TYPE mtk_device = MTK_LOGGER;
struct mtk_loginfo mtk_info;
"csv", &csv_file, "MTK compatible CSV output file",
NULL, ARGTYPE_STRING, ARG_NOMINMAX
},
+ {
+ "block_size", &OPT_block_size, "Size of blocks to request from device",
+ "1024", ARGTYPE_INT, "1024", "65536"
+ },
ARG_TERMINATOR
};
char cmd[256];
char* line = NULL;
unsigned char crc, *data = NULL;
- int cmdLen, j, bsize, i, len, ff_len, null_len, rc, init_scan, retry_cnt, log_enabled;
- unsigned int line_size, data_size, data_addr, addr, addr_max;
+ int cmdLen, i, len, rc, init_scan, retry_cnt, log_enabled;
+ unsigned int j, bsize, scan_bsize, read_bsize, scan_step, ff_len, null_len, chunk_size;
+ unsigned int line_size, data_size, data_addr, addr, addr_max, rcvd_addr, rcvd_bsize;
unsigned long dsize, dpos = 0;
FILE* dout;
char* fusage = NULL;
}
}
- bsize = 0x0400;
+ scan_step = 0x10000;
+ scan_bsize = 0x0400;
+ read_bsize = strtol(OPT_block_size, NULL, 0);
+ if (errno == ERANGE || read_bsize < 0x0400) {
+ read_bsize = 0x0400;
+ }
+ dbg(2, "Download block size is %d bytes\n", read_bsize);
+ if (init_scan) {
+ bsize = scan_bsize;
+ } else {
+ bsize = read_bsize;
+ }
addr = 0x0000;
- line_size = 2*bsize + 32; // logdata as nmea/hex.
- data_size = bsize + 32;
+ line_size = 2*read_bsize + 32; // logdata as nmea/hex.
+ data_size = read_bsize + 32;
if ((line = (char*) xmalloc(line_size)) == NULL) {
fatal(MYNAME ": Can't allocate %u bytes for NMEA buffer\n", line_size);
}
do_send_cmd(cmd, cmdLen);
memset(line, '\0', line_size);
+ rcvd_addr = addr;
do {
rc = gbser_read_line(fd, line, line_size-1, TIMEOUT, 0x0A, 0x0D);
if (rc != gbser_OK) {
if (strncmp(line, "$PMTK182,8", 10) == 0) { // $PMTK182,8,00005000,FFFFFFF
retry_cnt = 0;
data_addr = strtoul(&line[11], NULL, 16);
- fseek(dout, data_addr, SEEK_SET);
+ // fixme - we should check if all data before data_addr is already received
i = 20;
- j = 0;
+ j = data_addr - addr;
ff_len = 0; // number of 0xff bytes.
null_len = 0; // number of 0x00 bytes.
- while (i < (len-3)) {
+ while (i + 3 < len && j < data_size) {
data[j] = (isdigit(line[i])?(line[i]-'0'):(line[i]-'A'+0xA))*0x10 +
(isdigit(line[i+1])?(line[i+1]-'0'):(line[i+1]-'A'+0xA));
if (data[j] == 0xff) {
i += 2;
j++;
}
+ rcvd_addr = addr + j;
+ chunk_size = rcvd_addr - data_addr;
if (init_scan) {
- if (dsize > 0 && addr < dsize) {
- fseek(dout, addr, SEEK_SET);
- if (fread(line, 1, bsize, dout) == bsize && memcmp(line, data, bsize) == 0) {
- dpos = addr;
- dbg(2, "%s same at %d\n", TEMP_DATA_BIN, addr);
- } else {
- dbg(2, "%s differs at %d\n", TEMP_DATA_BIN, addr);
- }
- }
- if (ff_len == j) { // data in sector - we've found max sector..
- addr_max = addr;
+ if (ff_len == chunk_size) { // data in sector - we've found max sector..
+ addr_max = data_addr;
+ rcvd_addr = data_addr;
dbg(1, "Initial scan done - Download %dkB from device\n", (addr_max+1) >> 10);
+ break;
}
- len = 0;
} else {
- if (null_len == j) { // 0x00 block - bad block....
+ if (null_len == chunk_size) { // 0x00 block - bad block....
fprintf(stderr, "FIXME -- read bad block at 0x%.6x - retry ? skip ?\n%s\n", data_addr, line);
}
- if (fwrite(data, 1, j, dout) != j) {
- fatal(MYNAME ": Failed to write temp. binary file\n");
- }
- if (ff_len == j) { // 0xff block - read complete...
+ if (ff_len == chunk_size) { // 0xff block - read complete...
len = ff_len;
- addr_max = addr;
+ addr_max = data_addr;
+ rcvd_addr = data_addr;
break;
- } else {
- len = 0;
}
}
} else if (strncmp(line, "$PMTK001,182,7,", 15) == 0) { // Command ACK
}
}
}
- } while (len != 0);
+ } while (rcvd_addr < addr + bsize);
+
+ rcvd_bsize = rcvd_addr - addr;
+ dbg(2, "Received %d bytes\n", rcvd_bsize);
+
if (init_scan) {
- addr += 0x10000;
- if (addr >= addr_max) { // initial scan complete...
- init_scan = 0;
- addr = dpos;
+ if (dsize > 0 && addr < dsize) {
+ fseek(dout, addr, SEEK_SET);
+ if (fread(line, 1, rcvd_bsize, dout) == rcvd_bsize && memcmp(line, data, rcvd_bsize) == 0) {
+ dpos = addr;
+ dbg(2, "%s same at %d\n", TEMP_DATA_BIN, addr);
+ } else {
+ dbg(2, "%s differs at %d\n", TEMP_DATA_BIN, addr);
+ init_scan = 0;
+ addr = dpos;
+ bsize = read_bsize;
+ }
+ }
+ if (init_scan) {
+ addr += scan_step;
+ if (addr >= addr_max) { // initial scan complete...
+ init_scan = 0;
+ addr = dpos;
+ bsize = read_bsize;
+ }
}
} else {
- addr += bsize;
+ fseek(dout, addr, SEEK_SET);
+ if (fwrite(data, 1, rcvd_bsize, dout) != rcvd_bsize) {
+ fatal(MYNAME ": Failed to write temp. binary file\n");
+ }
+ addr += rcvd_bsize;
if (global_opts.verbose_status || (global_opts.debug_level >= 2 && global_opts.debug_level < 5)) {
int perc;
perc = 100 - 100*(addr_max-addr)/addr_max;
}
}
if (dout != NULL) {
+ ftruncate(fileno(dout), addr_max);
fclose(dout);
}
if (global_opts.verbose_status || (global_opts.debug_level >= 2 && global_opts.debug_level < 5)) {